
enum eState {
    show = '0', // 显示
    hide = '1', // 隐藏
    death = '2' // 死亡
}

export enum Eboundary {
    no,
    left,
    top,
    right,
    bottom,
    leftTop, // 左顶点
    rightTop, // 右顶点
    lefBottm, // 左脚点
    rightBottm // 右脚点
}

interface Ipos{
    x: number,
    y: number,
}

interface IMap {
    boundaryType: Eboundary, // 边界类型
    pos: Ipos, // 位置信息
    type: number, // 皮肤类型
    state: eState // 状态
}

interface iConfig {
    xNum?: number,
    yNum?: number,
    typeMax?: number
}

interface IcreateMapArrParams {
    startx: number,
    starty: number,
    offsetx: number,
    offsetY: number
}

class MatrixMap {

    public oConfig: iConfig = {
        xNum: 10,
        yNum: 10,
        typeMax: 5
    }

    public mapArr: IMap[] = [];

    public selectArrTemp: number[] = []; // 临时存储选中的点

    public starsTotal: number = 0; // 点位总数
    
    constructor(params?: iConfig) {
        if (this.oConfig) {
            this.oConfig = { ...this.oConfig, ...params }
        }
        this.starsTotal = this.oConfig.xNum * this.oConfig.yNum;
    }

    /**
     * 生成矩阵数据
     */
    public createMapArr(params: IcreateMapArrParams): IMap[] {
        const { xNum, yNum, typeMax } = this.oConfig;
        const { startx, starty, offsetx, offsetY } = params;
        for (let y = 0; y < yNum; y++) {
            for (let x = 0; x < xNum; x++) {
                const mapobj: IMap = {
                    pos: {
                        x: startx * x - offsetx,
                        y: starty * y - offsetY,
                    },
                    boundaryType: this.getBoundaryType(x, y),
                    type: Math.floor(Math.random() * typeMax),
                    state: eState.show
                }
                this.mapArr.push(mapobj)
            }
        }

        return this.mapArr
    }

    /**
     * 获取边界类型
     * @param x 
     * @param y 
     * @returns 
     */
    getBoundaryType(x: number, y: number): Eboundary{
        const { xNum, yNum } = this.oConfig;
        let boundaryType = null;
        const xdis = x % xNum;
        const ydis = y % yNum;
        const xmin = 0;
        const xmax = xNum - 1;
        const ymin = 0;
        const ymax = yNum - 1;
        
        switch(true){
            case xdis === xmin && ydis === ymin:{
                boundaryType = Eboundary.lefBottm
                break
            }
            case xdis === xmin && ydis === ymax:{
                boundaryType = Eboundary.leftTop
                break
            }
            case xdis === xmax && ydis === ymin:{
                boundaryType = Eboundary.rightBottm
                break
            }
            case xdis === xmax && ydis === ymax:{
                boundaryType = Eboundary.rightTop
                break
            }
            case xdis === xmin:{
                boundaryType = Eboundary.left
                break
            }
            case xdis === xmax:{
                boundaryType = Eboundary.right
                break
            }
            case ydis === ymin:{
                boundaryType = Eboundary.bottom
                break
            }
            case ydis === ymax:{
                boundaryType = Eboundary.top
                break
            }
        }

        return boundaryType
    }

    /**
     * 获取相邻的点集合
     */
    getAdjacentSpots(targetIndex: number): number[] {

        const target = this.mapArr[targetIndex];
        
        let arrx: number[] = this.filterBoundaryTypeOfIndex(target.boundaryType, targetIndex)
        
        arrx = arrx.filter((item: number) => {
            if (this.selectArrTemp.includes(item)) {
                return false
            }
            // 判断是否在合法的矩阵范围内
            if (item > 0 && item < this.starsTotal) {
                const itemNode = this.mapArr[item]
                // 判断类型相同，则命中,(距离合法或其他条件的判断应该到具体的业务中去做)
                if (itemNode.type === target.type) {
                    return true;
                }
            }
            return false;
        })

        arrx.forEach((item: number) => {
            if(item !== targetIndex){
                this.selectArrTemp.push(item)
                this.getAdjacentSpots(item)
            }
        })

        return this.selectArrTemp
    }

    /**
     * 过滤边界值，获取相邻点的位置索引
     * @param boundaryType 
     */
    filterBoundaryTypeOfIndex(boundaryType: Eboundary, targetIndex){
        switch(boundaryType){
            case Eboundary.leftTop:{
                return [
                    targetIndex, // self
                    targetIndex + 1, // right
                    -1, // top
                    -1, // left
                    targetIndex - this.oConfig.xNum // bottom
                ]
            }
            case Eboundary.lefBottm:{
                return [
                    targetIndex, // self
                    targetIndex + 1, // right
                    targetIndex + this.oConfig.xNum, // top
                    -1, // left
                    -1 // bottom
                ]
            }
            case Eboundary.rightTop:{
                return [
                    targetIndex, // self
                    -1, // right
                    -1, // top
                    targetIndex - 1, // left
                    targetIndex - this.oConfig.xNum // bottom
                ]
            }
            case Eboundary.rightBottm:{
                return [
                    targetIndex, // self
                    -1, // right
                    targetIndex + this.oConfig.xNum, // top
                    targetIndex - 1, // left
                    -1 // bottom
                ]
            }
            case Eboundary.left:{
                return [
                    targetIndex, // self
                    targetIndex + 1, // right
                    targetIndex + this.oConfig.xNum, // top
                    -1, // left
                    targetIndex - this.oConfig.xNum // bottom
                ]
            }
            case Eboundary.right:{
                return [
                    targetIndex, // self
                    -1, // right
                    targetIndex + this.oConfig.xNum, // top
                    targetIndex - 1, // left
                    targetIndex - this.oConfig.xNum // bottom
                ]
            }
            default:
                return [
                    targetIndex, // self
                    targetIndex + 1, // right
                    targetIndex + this.oConfig.xNum, // top
                    targetIndex - 1, // left
                    targetIndex - this.oConfig.xNum // bottom
                ]
        }
    }

    // 清空缓存的选择
    clearSelectArrTemp(){
        this.selectArrTemp = []
    }
}

export default MatrixMap;